package com.chenggong.window.activity.module

import android.Manifest
import android.content.pm.PackageManager
import android.media.MediaPlayer
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.widget.MediaController
import androidx.core.app.ActivityCompat
import com.arthenica.ffmpegkit.FFmpegKit
import com.arthenica.ffmpegkit.FFmpegKitConfig
import com.arthenica.ffmpegkit.ReturnCode
import com.chenggong.window.R
import com.chenggong.window.base.BaseActivity
import com.chenggong.window.databinding.ActivityModuleFfmpegBinding
import com.chenggong.window.utils.ResourcesUtil
import java.io.File
import java.io.IOException

class ModuleFfmpegActivity: BaseActivity<ActivityModuleFfmpegBinding>() {

    private val TAG = "ModuleFfmpegActivity"

    val REQUEST_EXTERNAL_STORAGE = 1
    var PERMISSIONS_ALL = arrayOf(
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.CAMERA
    )

    override val layoutId: Int
        get() = R.layout.activity_module_ffmpeg

    override fun initView(savedInstanceState: Bundle?) {
        // VERIFY PERMISSIONS
        var permission =
            ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
        if (permission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                this,
                PERMISSIONS_ALL,
                REQUEST_EXTERNAL_STORAGE
            )
        }
        permission =
            ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
        if (permission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                this,
                PERMISSIONS_ALL,
                REQUEST_EXTERNAL_STORAGE
            )
        }

        try {
            registerAppFont()
            Log.d(TAG, "Application fonts registered.")
        } catch (e: IOException) {
            Log.e(
                TAG,
                java.lang.String.format(
                    "Font registration failed.%s.",
                    e.toString()
                )
            )
        }

        mDataBinding.btnSubtitle.setOnClickListener {
            burnSubtitles()
        }
    }

    private fun getSubtitleFile(): File {
        return File(cacheDir, "subtitle.srt")
    }

    private fun getVideoFile(): File {
        return File(cacheDir, "video.mp4")
    }

    private fun registerAppFont() {
        if(getVideoFile().exists()){
            getVideoFile().delete()
        }

        if(getSubtitleFile().exists()){
            getSubtitleFile().delete()
        }

        ResourcesUtil.rawResourceToFile(
            resources,
            R.raw.video,
            getVideoFile()
        )

        ResourcesUtil.rawResourceToFile(
            resources,
            R.raw.subtitle,
            getSubtitleFile()
        )

        var cacheDirectory = File("/system/fonts")
        val fontNameMapping = HashMap<String, String>()
        if(!cacheDirectory.exists() || cacheDirectory.listFiles()?.isEmpty() == true){
            cacheDirectory = cacheDir

            ResourcesUtil.rawResourceToFile(
                resources,
                R.raw.doppioone_regular,
                File(cacheDirectory, "doppioone_regular.ttf")
            )
            ResourcesUtil.rawResourceToFile(
                resources,
                R.raw.truenorg,
                File(cacheDirectory, "truenorg.otf")
            )

            fontNameMapping["MyFontName"] = "doppioone_regular"
            fontNameMapping["truenorg"] = "truenorg"
            fontNameMapping["doppioone_regular"] = "doppioone_regular"
        }

        FFmpegKitConfig.setFontDirectory(this, cacheDirectory.absolutePath, fontNameMapping)
        FFmpegKitConfig.setEnvironmentVariable(
            "FFREPORT",
            String.format("file=%s", File(cacheDirectory.absolutePath, "ffreport.txt").absolutePath))
    }

    /**
     *  字幕样式设置：
     *  01.Name 风格(Style)的名称. 区分大小写. 不能包含逗号.
     *  02.Fontname 使用的字体名称, 区分大小写.
     *  03.Fontsize 字体的字号
     *  04.PrimaryColour 设置主要颜色, 为蓝-绿-红三色的十六进制代码相排列, BBGGRR. 为字幕填充颜色
     *  05.SecondaryColour 设置次要颜色, 为蓝-绿-红三色的十六进制代码相排列, BBGGRR. 在卡拉OK效果中由次要颜色变为主要颜色.
     *  06.OutlineColour 设置轮廓颜色, 为蓝-绿-红三色的十六进制代码相排列, BBGGRR.
     *  07.BackColour 设置阴影颜色, 为蓝-绿-红三色的十六进制代码相排列, BBGGRR. ASS的这些字段还包含了alpha通道信息. (AABBGGRR), 注ASS的颜色代码要在前面加上&amp;H
     *  08.Bold -1为粗体, 0为常规
     *  09.Italic -1为斜体, 0为常规
     *  10.Underline [-1 或者 0] 下划线
     *  11.Strikeout [-1 或者 0] 中划线/删除线
     *  12.ScaleX 修改文字的宽度. 为百分数
     *  13.ScaleY 修改文字的高度. 为百分数
     *  14.Spacing 文字间的额外间隙. 为像素数
     *  15.Angle 按Z轴进行旋转的度数, 原点由alignment进行了定义. 可以为小数
     *  16.BorderStyle 1=边框+阴影, 3=纯色背景. 当值为3时, 文字下方为轮廓颜色的背景, 最下方为阴影颜色背景.
     *  17.Outline 当BorderStyle为1时, 该值定义文字轮廓宽度, 为像素数, 常见有0, 1, 2, 3, 4.
     *  18.Shadow 当BorderStyle为1时, 该值定义阴影的深度, 为像素数, 常见有0, 1, 2, 3, 4.
     *  19.Alignment 定义字幕的位置. 字幕在下方时, 1=左对齐, 2=居中, 3=右对齐. 1, 2, 3加上4后字幕出现在屏幕上方. 1, 2, 3加上8后字幕出现在屏幕中间. 例: 11=屏幕中间右对齐. Alignment对于ASS字幕而言, 字幕的位置与小键盘数字对应的位置相同.
     *  20.MarginL 字幕可出现区域与左边缘的距离, 为像素数
     *  21.MarginR 字幕可出现区域与右边缘的距离, 为像素数
     *  22.MarginV 垂直距离
     */

    private fun burnSubtitles(){
        val videoFile = getVideoFile()
        val subtitleFile = getSubtitleFile()
        if(!videoFile.exists() || !subtitleFile.exists()){
            return
        }
        val videoWithSubtitlesFile = File(cacheDir, "subtitle_video.mp4")
        val burnSubtitlesCommand = String.format(
            "-y -i %s -vf subtitles=%s:force_style='Fontsize=20\\,Alignment=6\\,Shadow=1\\,PrimaryColour=&H2328C4' %s",//格式：BBGGRR-红色和蓝色对调，奇了个怪
            videoFile.absolutePath,
            subtitleFile.absolutePath,
            videoWithSubtitlesFile.absolutePath
        )


        FFmpegKit.executeAsync(
            burnSubtitlesCommand
        ) { session ->//FFmpegSession session
            Log.d(
                TAG,
                String.format("FFmpegKit process exited with rc %d.", session.returnCode.value))
            when (session.returnCode.value) {
                ReturnCode.SUCCESS -> {
                    Log.d(TAG, "Burn subtitles completed successfully; playing video.")
                    playVideo(videoWithSubtitlesFile.absolutePath)
                }
                ReturnCode.CANCEL -> {
                    Log.e(TAG, "Burn subtitles operation cancelled")
                }
                else -> {
                    Log.e(
                        TAG,
                        String.format("Burn subtitles failed with rc=%d.", session.returnCode.value)
                    )
                }
            }
        }
    }

    protected fun playVideo(path: String) {
        mDataBinding.videoView.post {
            val mediaController = MediaController(this)
            mediaController.setAnchorView(mDataBinding.videoView)
            mDataBinding.videoView.setVideoURI(Uri.parse("file://$path"))
            mDataBinding.videoView.setMediaController(mediaController)
            mDataBinding.videoView.requestFocus()
            mDataBinding.videoView.setOnPreparedListener(MediaPlayer.OnPreparedListener {
                mDataBinding.videoView.setBackgroundColor(
                    0x00000000
                )
            })
            mDataBinding.videoView.setOnErrorListener(MediaPlayer.OnErrorListener { mp, what, extra ->
                mDataBinding.videoView.stopPlayback()
                false
            })
            mDataBinding.videoView.start()
        }
    }

}